﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace JkUtils
{
    public static class ObjectExtension
    {
        /// <summary>
        /// 判定对象不为 null
        /// </summary>
        /// <returns></returns>
        public static bool JkNotNull(this object obj) { return obj != null; }

        /// <summary>
        /// 判定对象为 null
        /// </summary>
        /// <returns></returns>
        public static bool JkIsNull(this object obj) { return obj == null; }

        /// <summary>
        /// 转换为 JSON
        /// </summary>
        /// <param name="obj">要序列化的对象</param>
        /// <param name="indented">是否格式化</param>
        /// <param name="settings">序列化设置</param>
        /// <returns></returns>
        public static string ToJson(this object obj, bool indented = false, JsonSerializerSettings settings = null)
        {
            return obj.JkIsNull() ? null :
                JsonConvert.SerializeObject(
                    obj,
                    indented ? Formatting.Indented : Formatting.None,
                    settings ?? new JsonSerializerSettings() { DateFormatString = "yyyy-MM-dd HH:mm:ss" });
        }

        /// <summary>
        /// 强制转换为指定对象 , 简化写法, 出错不管
        /// </summary>
        /// <typeparam name="T">目标类型</typeparam>
        /// <param name="obj">要转换的对象</param>
        /// <returns></returns>
        public static T JkTo<T>(this object obj) { return (T)obj; }

        /// <summary>
        /// 将object对象转换为实体对象
        /// </summary>
        /// <typeparam name="T">实体对象类名</typeparam>
        /// <param name="asObject">object对象</param>
        /// <returns></returns>
        public static T JkObjTo<T>(object asObject) where T : new()
        {
            //创建实体对象实例
            var t = Activator.CreateInstance<T>();
            if (asObject != null)
            {
                Type type = asObject.GetType();
                //遍历实体对象属性
                foreach (var info in typeof(T).GetProperties())
                {
                    //取得object对象中此属性的值
                    var val = type.GetProperty(info.Name)?.GetValue(asObject);
                    if (val != null)
                    {
                        object obj;
                        //非泛型
                        if (!info.PropertyType.IsGenericType)
                            obj = Convert.ChangeType(val, info.PropertyType);
                        else//泛型Nullable<>
                        {
                            Type genericTypeDefinition = info.PropertyType.GetGenericTypeDefinition();
                            if (genericTypeDefinition == typeof(Nullable<>))
                            {
                                obj = Convert.ChangeType(val, Nullable.GetUnderlyingType(info.PropertyType));
                            }
                            else
                            {
                                obj = Convert.ChangeType(val, info.PropertyType);
                            }
                        }
                        info.SetValue(t, obj, null);
                    }
                }
            }
            return t;
        }

        /// <summary>
        /// 获取属性
        /// </summary>
        /// <typeparam name="T">属性类型</typeparam>
        /// <param name="p">要获取的对象</param>
        /// <param name="key">属性名</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns></returns>
        public static T JkProp<T>(this object p, string key, T defaultValue = default)
        {
            if (p == null) return defaultValue;
            var type = p.GetType();

            var prop = type.GetProperty(key, BindingFlags.Public | BindingFlags.Instance);
            if (prop == null) return defaultValue;

            var value = prop.GetValue(key, null);
            if (value == null) return defaultValue;

            try { return value.ToJson().JkToObject<T>(); }
            catch (Exception e)
            {
                Console.WriteLine(e);
                return defaultValue;
            }
        }

        /// <summary>
        /// 获取字符串属性
        /// </summary>
        /// <param name="p">要获取的对象</param>
        /// <param name="key">属性值</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns></returns>
        public static string JkPropString(this object p, string key, string defaultValue = null)
        {
            if (p == null) return defaultValue;
            var type = p.GetType();

            var prop = type.GetProperty(key, BindingFlags.Public | BindingFlags.Instance);
            if (prop == null) return defaultValue;

            var value = prop.GetValue(key, null);
            if (value == null) return defaultValue;

            var valEncStr = value as string;
            return valEncStr ?? defaultValue;
        }

        /// <summary>
        /// 转换到 <see cref="byte"/> 值
        /// </summary>
        /// <param name="obj">要转化的值</param>
        /// <returns></returns>
        public static byte JkToByte(this object obj)
        {
            return Convert.ToByte(obj);
        }

        /// <summary>
        /// 转换到 <see cref="int"/> 值
        /// </summary>
        /// <param name="obj">要转化的值</param>
        /// <returns></returns>
        public static int JkToInt32(this object obj)
        {
            return Convert.ToInt32(obj);
        }

        /// <summary>
        /// 转换到 <see cref="long"/> 值
        /// </summary>
        /// <param name="obj">要转化的值</param>
        /// <returns></returns>
        public static long JkToInt64(this object obj)
        {
            return Convert.ToInt64(obj);
        }

        /// <summary>
        /// 转换到 <see cref="float"/> 值
        /// </summary>
        /// <param name="obj">要转化的值</param>
        /// <returns></returns>
        public static float JkToSingle(this object obj)
        {
            return Convert.ToSingle(obj);
        }

        /// <summary>
        /// 转换到 <see cref="double"/> 值
        /// </summary>
        /// <param name="obj">要转化的值</param>
        /// <returns></returns>
        public static double JkToDouble(this object obj)
        {
            return Convert.ToDouble(obj);
        }

        /// <summary>
        /// 转换到 <see cref="decimal"/> 值
        /// </summary>
        /// <param name="obj">要转化的值</param>
        /// <returns></returns>
        public static decimal JkToDecimal(this object obj)
        {
            return Convert.ToDecimal(obj);
        }

        /// <summary>
        /// 转换到 <see cref="bool"/> 值
        /// </summary>
        /// <param name="obj">要转化的值</param>
        /// <returns></returns>
        public static bool JkToBool(this object obj)
        {
            if (obj == null) return false;
            // 如果是字符串且空白字符串，返回 false
            if (obj.GetType() == typeof(string) && obj.ToString().Trim() == "") return false;
            return Convert.ToBoolean(obj);
        }

        /// <summary>
        /// 将 <see cref="int"/> 转换到 <see cref="byte"/>
        /// </summary>
        /// <param name="value"><see cref="int"/> 值</param>
        /// <returns></returns>
        public static byte JkToByte(this int value)
        {
            return Convert.ToByte(value);
        }
        /// <summary>
        /// 将匹配的分组指定下标项转为字符串
        /// </summary>
        /// <param name="group"></param>
        /// <param name="index"></param>
        /// <returns></returns>
        public static string IndexToStrring(this GroupCollection group, int index)
        {
            return group[index].Value.ToString();
        }
        /// <summary>
        /// 将匹配的分组指定下标项转为32位整形
        /// </summary>
        /// <param name="group">匹配到的分组</param>
        /// <param name="index">下标索引</param>
        /// <returns></returns>
        public static int IndexToInt32(this GroupCollection group, int index)
        {
            return group[index].Value.JkToInt32();
        }
        /// <summary>
        /// 将匹配的分组指定下标项转为64位整形
        /// </summary>
        /// <param name="group">匹配到的分组</param>
        /// <param name="index">下标索引</param>
        /// <returns></returns>
        public static long IndexToInt64(this GroupCollection group, int index)
        {
            return group[index].Value.JkToInt64();
        }
        /// <summary>
        /// 将匹配的分组指定下标项转为浮点数
        /// </summary>
        /// <param name="group">匹配到的分组</param>
        /// <param name="index">下标索引</param>
        /// <returns></returns>
        public static float IndexToFloat(this GroupCollection group, int index)
        {
            return group[index].Value.JkToSingle();
        }
    }
}
